﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PersonaLibrary.Data;
using System.Linq.Expressions;

namespace PersonaLibrary.Search
{
    public sealed class SimplySearch
    {
        private string searched;

        private readonly Dictionary<string, KeyValuePair<int, IEnumerable>> _searchResult = new Dictionary<string, KeyValuePair<int, IEnumerable>>();

        public IDictionary<string, KeyValuePair<int, IEnumerable>> SearchResult { get { return _searchResult; } }

        public SimplySearch(string searched)
        {
			Stopwatch sw = new Stopwatch();
			sw.Start();
            this.searched = searched;

			Task<KeyValuePair<string, KeyValuePair<int, IEnumerable>>> orgTask = new Task<KeyValuePair<string, KeyValuePair<int, IEnumerable>>>
				(
				() =>
					{
						LinqToDbDataContext orgContext = new LinqToDbDataContext();
						var orgResult = orgContext.Organizations.Where(SearchOrganizations).AsEnumerable();
						return new KeyValuePair<string, KeyValuePair<int, IEnumerable>>("Орагнизации", new KeyValuePair<int, IEnumerable>(orgResult.Count(), orgResult));
					}
				);

            orgTask.Start();

			Task<KeyValuePair<string, KeyValuePair<int, IEnumerable>>> empTask = new Task<KeyValuePair<string, KeyValuePair<int, IEnumerable>>>
				(
				() =>
				{
					LinqToDbDataContext empContext = new LinqToDbDataContext();
					var empResult = empContext.Employees.Where(SearchEmployees).AsEnumerable();
					return new KeyValuePair<string, KeyValuePair<int, IEnumerable>>("Сотрудники", new KeyValuePair<int, IEnumerable>(empResult.Count(), empResult));
				}
				);
			empTask.Start();

			Task<KeyValuePair<string, KeyValuePair<int, IEnumerable>>> notTask = new Task<KeyValuePair<string, KeyValuePair<int, IEnumerable>>>
				(
				() =>
				{
					LinqToDbDataContext notContext = new LinqToDbDataContext();
					var result = notContext.Notes.Where(SearchNote).AsEnumerable();
					return new KeyValuePair<string, KeyValuePair<int, IEnumerable>>("Примечания", new KeyValuePair<int, IEnumerable>(result.Count(), result));
				}
				);
			notTask.Start();

			Task<KeyValuePair<string, KeyValuePair<int, IEnumerable>>> jobTask = new Task<KeyValuePair<string, KeyValuePair<int, IEnumerable>>>
				(
				() =>
				{
					LinqToDbDataContext jobContext = new LinqToDbDataContext();
					var result = jobContext.Jobs.Where(SearchConnection).AsEnumerable();
					return new KeyValuePair<string, KeyValuePair<int, IEnumerable>>("Должности", new KeyValuePair<int, IEnumerable>(result.Count(), result));
				}
				);
			jobTask.Start();

        	Task.WaitAll(orgTask, empTask, notTask,jobTask);
			_searchResult.Add(orgTask.Result.Key, orgTask.Result.Value);
			_searchResult.Add(empTask.Result.Key, empTask.Result.Value);
			_searchResult.Add(notTask.Result.Key, notTask.Result.Value);
			_searchResult.Add(jobTask.Result.Key, jobTask.Result.Value);

			sw.Stop();
			Debug.WriteLine(sw.Elapsed);
        }

        private bool SearchOrganizations(Organization arg)
        {
            var result = false;
            if (arg.Name != null)
                if (arg.Name.ToUpper().Contains(searched.ToUpper())) result = true;
            if (arg.Category != null)
                if (arg.Category.ToUpper().Contains(searched.ToUpper())) result = true;
            if (arg.Ownership != null)
                if (arg.Ownership.ToUpper().Contains(searched.ToUpper())) result = true;
            if (arg.Legaladdress != null)
                if (arg.Legaladdress.ToUpper().Contains(searched.ToUpper())) result = true;
            if (arg.Legalphone != null)
                if (arg.Legalphone.ToUpper().Contains(searched.ToUpper())) result = true;
            foreach (var department in arg.Departments)
                if (department.Name != null)
                    if (department.Name.ToUpper().Contains(searched.ToUpper())) result = true;


            return result;
        }

        private bool SearchEmployees(Employee arg)
        {
            if (arg.Name != null)
                if (arg.Name.ToUpper().Contains(searched.ToUpper())) return true;
            if (arg.Surname != null)
                if (arg.Surname.ToUpper().Contains(searched.ToUpper())) return true;
            if (arg.Patronymic != null)
                if (arg.Patronymic.ToUpper().Contains(searched.ToUpper())) return true;
            if (arg.PersonalAdress != null)
                if (arg.PersonalAdress.ToUpper().Contains(searched.ToUpper())) return true;
            if (arg.PersonalPhone != null)
                if (arg.PersonalPhone.ToUpper().Contains(searched.ToUpper())) return true;
            if (arg.Id.Equals(searched)) return true;
            if (arg.Birthday.HasValue)
                if (arg.Birthday.Value.ToString("MMMM").ToUpper().Equals(searched.ToUpper())) 
                    return true;
            foreach (var con in arg.ConnectionJobEmplDeps)
            {
                if(con.Job.Name.ToUpper().Contains(searched.ToUpper())) return true;
                if (con.Department.Name.ToUpper().Contains(searched.ToUpper())) return true;
                if (con.Department.Organization.Name.ToUpper().Contains(searched.ToUpper())) return true;
            }

            return false;
        }

        private bool SearchNote(Note arg)
        {
            if (arg.Name != null)
                if (arg.Name.ToUpper().Contains(searched.ToUpper())) return true;
            if (arg.Id.Equals(searched)) return true;
            return false;
        }

        private bool SearchConnection(Job arg)
        {
            if (arg.Name != null)
                if (arg.Name.ToUpper().Contains(searched.ToUpper()))
                    return true;
            return false;
        }
    }
}
